package com.by.service.impl;

import com.by.bean.Minio;
import com.by.service.MinioService;
import io.minio.*;
import io.minio.http.Method;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Service
public class MinioServiceImpl implements MinioService {
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private Minio minio;
    //1.上传/*需要自己创建桶*/
    public String upload(MultipartFile file) {
        try {
            // 检查桶是否存在（关键修正：使用BucketExistsArgs.builder()）
            boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minio.getBucketName()).build()
            );
            // 如果桶不存在，创建桶
            if (!exists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(minio.getBucketName()).build()
                );
            }
            // 生成文件名（日期+UUID+原文件后缀）
            String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String uuid = UUID.randomUUID().toString();
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFileName = uuid + extension;
            String fileName = dateTime + "/" + newFileName; // 最终存储路径：日期/UUID.后缀
            // 上传文件到MinIO
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(minio.getBucketName())
                            .object(fileName)
                            .stream(file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build()
            );
            // 生成访问URL
            String url =  fileName;
            return url;

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件上传失败：" + e.getMessage());
        }
    }
    /**
     * 文件下载方法
     *
     * @param objectName 上传时生成的完整文件名（包含日期路径，如：2023-10-01/xxx-xxx.jpg）
     * @param response   Http响应对象
     */
    public void download(String objectName, HttpServletResponse response) {
        try {
            String bucketName = minio.getBucketName();
            // 1. 获取文件类型（通过 MinIO 客户端查询文件元数据）
            StatObjectResponse stat = minioClient.statObject(
                    StatObjectArgs.builder().bucket(bucketName).object(objectName).build()
            );
            String contentType = stat.contentType(); // 例如：image/png、application/pdf 等

            // 2. 设置响应头
            response.setContentType(contentType); // 设置文件 MIME 类型
            // 处理中文文件名乱码，并指定为附件（触发下载）
            String fileName = objectName.substring(objectName.lastIndexOf("/") + 1);
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
                    .replaceAll("\\+", "%20"); // 替换空格为 %20
            response.setHeader("Content-Disposition",
                    "attachment;filename*=UTF-8''" + encodedFileName); // 关键：指定为附件下载

            // 3. 写入文件流
            try (InputStream in = minioClient.getObject(
                    GetObjectArgs.builder().bucket(bucketName).object(objectName).build()
            )) {
                IOUtils.copy(in, response.getOutputStream()); // 使用 commons-io 工具类高效拷贝流
                response.flushBuffer(); // 刷新响应
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件下载失败：" + e.getMessage());
        }
    }
    /**
     * 文件预览方法（生成临时访问URL）
     * @param objectName 上传时生成的完整文件名（包含日期路径，如：2023-10-01/xxx-xxx.jpg）
     * @param expires 预览链接有效期（秒），默认3600秒（1小时）
     * @return 可直接在浏览器打开的预览URL
     */
    public String preview(String objectName, int expires) {
        try {
            // 检查存储桶是否存在
            boolean bucketExists = minioClient.bucketExists(
                    BucketExistsArgs.builder().bucket(minio.getBucketName()).build()
            );
            if (!bucketExists) {
                throw new RuntimeException("存储桶不存在");
            }

            // 生成临时访问URL，支持GET方法（预览）
            String previewUrl = minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(minio.getBucketName())
                            .object(objectName)
                            .expiry(expires) // 有效期（秒）
                            .build()
            );
            return previewUrl;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取预览链接失败：" + e.getMessage());
        }
    }

    // 重载preview方法，使用默认有效期（1小时）
    public String preview(String objectName) {
        return preview(objectName, 3600);
    }




}
